#pragma once
#include "RenderCommon.h"
#include "RenderContext.h"
#include "Interpolator.h"
#include <vector>

typedef enum
{
	ERenderModeMesh		= 0, 
	ERenderModeLayer, 
	ERenderModeSolid, 
	ERenderModeCount
}ERenderMode;

typedef enum
{
	EInterpolateModeIDW		= 0, 
	EInterpolateModeKriging
}EInterpolateMode;

typedef void (*ProgressCallback)(int nPercent, LPVOID pContext);

class CStratumRender
{
public:
	CStratumRender(CRenderContext* pContext);
	virtual ~CStratumRender();

	HRESULT SetData(
		const CArray2D<glm::vec3>* pDrillData, 
		glm::vec4* pPorosityData, UINT uiPorosityCount, 
		glm::vec4* pSaturationData, UINT uiSaturationCount);
	HRESULT SetInterpolateMode(EInterpolateMode eMode);
	HRESULT SetDrillRadius(float fRadius);
	HRESULT SetMeshDimension(UINT uiWidth, UINT uiHeight, UINT uiDepth);
	HRESULT SetBackgroundColor(COLORREF dwColor);

	BOOL IsRebuildNeeded() { return m_bRebuildNeeded; }
	HRESULT BuildModel(ProgressCallback pCallback, LPVOID pContext);

	HRESULT ResetPosition();
	HRESULT BeginTransform();
	HRESULT Translate(float fX, float fY, float fZ);
	HRESULT Scale(float fX, float fY, float fZ);
	HRESULT Rotate(float fX, float fY, float fZ);
	HRESULT EndTransform();

	HRESULT ClearScreen();
	HRESULT RenderDrills(ERenderMode eMode, const std::vector<bool>& cVisibilities);
	HRESULT RenderStratums(ERenderMode eMode, const std::vector<bool>& cVisibilities, BOOL bShadeByDensity);
	HRESULT GetDrillColor(UINT uiDrill, COLORREF& dwColor);
	HRESULT GetStratumColor(UINT uiStratum, COLORREF& dwColor);
	HRESULT GetResourceAmount(float* pfAmount);

private:
	CRenderContext* m_pRenderContext;

	typedef struct
	{
		int* pIndexBuffers[ERenderModeCount];
		UINT uiIndexCounts[ERenderModeCount];
	}SModel;

	BOOL m_bRebuildNeeded;

	//input data
	const CArray2D<glm::vec3>* m_pDrillData;
	glm::vec4* m_pPorosityData;
	UINT m_uiPorosityCount;
	glm::vec4* m_pSaturationData;
	UINT m_uiSaturationCount;

	EInterpolateMode m_eInterpolateMode;
	float m_fDrillRadius;
	UINT m_uiMeshWidth;
	UINT m_uiMeshHeight;
	UINT m_uiMeshDepthOrigin;
	UINT m_uiMeshDepth;
	glm::vec4 m_stBackgroundColor;

	//model data
	glm::vec3 m_stBoundBoxMin;
	glm::vec3 m_stBoundBoxMax;

	SRenderVertex* m_pDrillVertexBuffer;
	UINT m_uiDrillVertexCount;
	std::vector<SModel> m_cDrillModels;

	SRenderVertex* m_pStratumVertexBuffer1; //shade by stratum index
	SRenderVertex* m_pStratumVertexBuffer2; //shade by density
	UINT m_uiStratumVertexCount;
	std::vector<SModel> m_cStratumModels;

	float m_fMaxDensity;

	//transform
	glm::mat4 m_stWorldMatrix;
	BOOL m_bTransformBegined;
	glm::mat4 m_stOriginWorldMatrix;

	glm::vec3 GetCenter();
	glm::mat4 GetWorldViewProjMatrix();

	void FillDrillVertexBuffer();
	void FillDrillModels();
	void FillStratumVertexBuffer();
	void FillStratumModels();

	IInterpolator* CreateInterpolator();
	void DestroyModel();
	float GetStratumDensity(
		IInterpolator* pPorosityInterpolator, 
		IInterpolator* pSaturationInterpolator, 
		glm::vec4& stPosition);

	void RenderBoundBox();
	void RenderLegend();
};